#include <rtthread.h>
#include <rtdevice.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#ifdef RT_USING_VIDEO
#if 0
static rt_device_t dev = 0;
static struct rt_device_graphic_info info;

static int lcd_init(void)
{
    int result;

    if (dev)
        return 0;

    dev = rt_device_find("lcd");
    if (!dev)
        return -1;

    if (rt_device_open(dev, 0) != 0)
    {
        dev = 0;
        return -1;
    }

    result = rt_device_control(dev, RTGRAPHIC_CTRL_GET_INFO, &info);
    if (result != 0)
    {
        rt_device_close(dev);
        dev = 0;
        return result;
    }

    return 0;
}

static int lcd_fill_point(int x, int y, uint16_t c)
{
    uint16_t *fb = (uint16_t *)info.framebuffer;

    if ((x < 0) || (y < 0) || (x >= info.width) || (y >= info.height))
        return -1;

    fb += x;
    fb += (y * info.width);

    *fb = c;

    return 0;
}

static void lcd_update(int x, int y, int w, int h)
{
    struct rt_device_rect_info rect;

    if (x < 0)
    {
        w += x;
        x = 0;
    }
    if (y < 0)
    {
        h += y;
        y = 0;
    }
    if ((x > info.width) || (y > info.height))
        return;

    if ((x + w) > info.width)
        w = info.width - x;
    if ((y + h) > info.height)
        h = info.height - h;

    if ((w < 1) || (h < 1))
        return;

    rect.x = x;
    rect.y = y;
    rect.width = w;
    rect.height = h;

    rt_device_control(dev, RTGRAPHIC_CTRL_RECT_UPDATE, &rect);
}

static void lcd_show_image(int x, int y, int length, int wide, const rt_uint8_t *buf)
{
    uint16_t *color = (uint16_t *)buf;
    int h, w;

    if (lcd_init() != 0)
        return;

    for (h = 0; h < length; h++)
    {
        for (w = 0; w < wide; w++)
        {
            lcd_fill_point(x + w, y + h, *color);
            color++;
        }
    }

    lcd_update(x, y, wide, length);
}
#else
#define lcd_show_image(...)
#endif

static int vidc1(int argc, char *argv[])
{
    int fd;
    struct video_requestbuffers reqbufs;
    struct video_buffer vb;
    enum video_type vt = VIDEO_TYPE_CAPTURE;
    int ret;

    fd = open(":dev/video0", O_RDWR);
    if (fd < 0)
    {
        printf("dev not found");
        return -1;
    }

    printf("open ok\n");
    reqbufs.count = 1;

    ret = ioctl(fd, VIDIOC_REQBUFS, &reqbufs);
    printf("REQBUFS %d\n", ret);
    vb.type = VIDEO_TYPE_CAPTURE;
    vb.index = 0;
    ret = ioctl(fd, VIDIOC_QUERYBUF, &vb);
    printf("QUERYBUF %d\n", ret);
    ret = ioctl(fd, VIDIOC_QBUF, &vb);
    printf("QBUF %d\n", ret);
    ret = ioctl(fd, VIDIOC_STREAMON, &vt);
    printf("STREAMON %d\n", ret);

    while (1)
    {
        rt_thread_mdelay(1000);
    }

    close(fd);

    return 0;
}
MSH_CMD_EXPORT(vidc1, video capture test1);

static int vidc2(int argc, char *argv[])
{
    int fd;
    struct video_format fmt;
    char *buf;
    int ret;

    fd = open(":dev/video0", O_RDWR);
    if (fd < 0)
    {
        printf("dev not found");
        return -1;
    }

    fmt.type = VIDEO_TYPE_CAPTURE;
    fmt.fmt.pix.width = 320;
    fmt.fmt.pix.height = 240;
    fmt.fmt.pix.pixelformat = VIDEO_PIX_FMT_RGB565;

    if (ioctl(fd, VIDIOC_S_FMT, &fmt) != 0)
    {
        printf("S_FMT fail\n");
        goto _out;
    }

    buf = rt_malloc(320 * 240 * 2);
    if (!buf)
        goto _out;

    ret = read(fd, buf, 320 * 240 * 2);

_out:
    close(fd);

    return 0;
}
MSH_CMD_EXPORT(vidc2, video capture test2);

static int vidshow(int argc, char *argv[])
{
    int fd;
    struct video_format fmt;
    char *buf;
    int ret;
    int cnt = 1000;

    while ((--argc) > 0)
    {
        if (strncmp(argv[argc], "-c", 2) == 0)
            cnt = atoi(&argv[argc][2]);
    }

    printf("open video...\n");

    fd = open(":dev/video0", O_RDWR);
    if (fd < 0)
    {
        printf("dev not found");
        return -1;
    }

    fmt.type = VIDEO_TYPE_CAPTURE;
    fmt.fmt.pix.width = 320;
    fmt.fmt.pix.height = 240;
    fmt.fmt.pix.pixelformat = VIDEO_PIX_FMT_RGB565;

    printf("set fmt...\n");

    if (ioctl(fd, VIDIOC_S_FMT, &fmt) != 0)
    {
        printf("S_FMT fail\n");
        goto _out;
    }

    buf = malloc(320 * 240 * 2);
    if (!buf)
        goto _out;

    printf("read video count(%d)...\n", cnt);

    while (cnt--)
    {
        ret = read(fd, buf, 320 * 240 * 2);
        if (ret != 320 * 240 * 2)
        {
            printf("read fail %d\n", ret);
            break;
        }
        rt_thread_mdelay(10);
        lcd_show_image(0, 0, 240, 320, buf);
    }

    free(buf);

_out:
    close(fd);

    return 0;
}
MSH_CMD_EXPORT(vidshow, video capture and show on lcd);

#endif
